
#include "cscan.h"



int getCilindro(int pos, chs auxChs)
{
	int resultado, resto;
	resto = pos%auxChs.sectores;
	if(resto == 0) /* el sector es el ultimo del cilindro por ser multiplo de los sectores y pasa porque los sectores arrancan de 1 */
	{
		resultado = pos/auxChs.sectores;
	}
	else
	{
		resultado = pos/auxChs.sectores +1;
	}
	return resultado;

}

int girarElDisco(int pos, int sectoresPorPista)
{
	int resultado,resto;
	resto = pos%sectoresPorPista;
	if(resto == 0)
	{
		resultado = pos - (sectoresPorPista -1);
	}
	else
	{
		resultado = pos +1;
	}
	return resultado;
}

int sectorProximoCilindro( int auxSector, chs auxChs )
{
	int resultado;
	resultado = auxSector + auxChs.sectores;
	return resultado;
}

int caerDeCilindro(int pos, int cilindros, int cantidadSectores)
{
	int resultado;
	resultado = pos - ((cilindros-1)*cantidadSectores);
	return resultado;
}

int tipoDePista(int pos, int buscada, chs auxChs)
{
	int a,b;
	a = getCilindro(pos,auxChs);
	b = getCilindro(buscada,auxChs);

	if(a == b)
	{
		return PISTA_MISMA;
	}
	else if ( b < a)
	{
		return PISTA_MENOR;
	}
	else
	{
		return PISTA_MAYOR;
	}
}

int haySectores(cola_sectores sectores[30]) {
    int i;
    for(i=0;i<30;i++)
	{
		if(sectores[i].numeroDeSector != -1)
		{
			return 1;
		}
	}
    return 0;
}

int haySectorEnPista(cola_sectores sectores[30], int cilindro, chs auxChs)
{
	int resultado, i;
	resultado = 0;

	for(i=0; i<30; i++)
	{
		if(getCilindro(sectores[i].numeroDeSector, auxChs) == cilindro && sectores[i].numeroDeSector != -1)
		{
			resultado = 1;
		}
	}
	return resultado;
}

void init(cola_sectores sectores[30])
{
	int i;
	for(i=0;i<30;i++)
	{
		sectores[i].numeroDeSector = -1;
	}
}

void ordenarSectores(cola_sectores sectores[30],cola_sectores sectoresOrdenados[30])
{
	int i,b;
	init(sectoresOrdenados);

	i=0;
	for(b=0; b<30 || sectores[b].numeroDeSector == -1; b++)
	{
		sectoresOrdenados[i] = sectores[b];
		sectores[b].numeroDeSector = -1;
		i++;
	}

}

int haySectoresCilindrosMayores(cola_sectores sectores[30], int cilindro, chs auxChs)
{
	int resultado, i;
	resultado = 0;

	for(i=0; i<30; i++)
	{
		if(getCilindro(sectores[i].numeroDeSector, auxChs) > cilindro)
		{
			resultado = 1;
		}
	}
	return resultado;
}

/* Le pasas un array con hasta 30 sectores (los no validos van en -1) y te lo devuelve ordenado segun C-SCAN */
int ordenarCola(cola_sectores sectores[30], int actual, chs auxChs)
{
	cola_sectores resultadoSectores[30];
	cola_sectores sectoresOrdenados[30];
	cola_sectores aux;
	int i,e,a;

	ordenarSectores(sectores,sectoresOrdenados);

	for(i=0;i<30;i++)
	{
		resultadoSectores[i].numeroDeSector = -1;
	}

	e = 0;

	while(haySectores(sectoresOrdenados))
	{
		if(haySectorEnPista(sectoresOrdenados, getCilindro(actual,auxChs), auxChs))
		{
			for(i=0; i<30; i++)
			{
				for(a=0; a<30; a++)
				{
					if(actual == sectoresOrdenados[i].numeroDeSector)
					{
						resultadoSectores[e] = sectoresOrdenados[i];
						e++;
						sectoresOrdenados[i].numeroDeSector = -1;
						break;
					}

					if((resultadoSectores[a].numeroDeSector == resultadoSectores[a+1].numeroDeSector) && ((resultadoSectores[a].tipoDePedido == L) && (resultadoSectores[a+1].tipoDePedido == E)))
					{
						aux = resultadoSectores[a];
						resultadoSectores[a] = resultadoSectores[a+1];
						resultadoSectores[a+1] = aux;
					} // ordena array por 2 claves (numeroDeSector y tipoDePedido)

				}
			}
			actual = girarElDisco(actual, auxChs.sectores);
		}
		else if(haySectoresCilindrosMayores(sectoresOrdenados, getCilindro(actual, auxChs), auxChs))
		{
			actual = sectorProximoCilindro( actual, auxChs);
		}
		else
		{
			actual = caerDeCilindro(actual, getCilindro(actual, auxChs),  auxChs.sectores);
		}
	}


	for(i=0;i<30;i++)
	{
		sectoresOrdenados[i] = resultadoSectores[i];
	}

	e=0;
	for(i=0;i<30;i++)
	{
		if(sectoresOrdenados[e].numeroDeSector != -1)
		{
			sectores[i] = sectoresOrdenados[e];
			e++;
		}
	}

	return 0;

}

void traceCSCAN (int posActual, int secBuscado, int proxSector, config Conf)
{
	ps PS_Actual, PS_Buscado, PS_Proximo;
	float tiempoConsumido;
	PS_Actual = pasarA_pistaSector (posActual, Conf);
	PS_Buscado = pasarA_pistaSector (secBuscado, Conf);
	PS_Proximo = pasarA_pistaSector (proxSector, Conf);
	printf("Posición actual: %i:%i\n", PS_Actual.pista, PS_Actual.sector);
	printf("Sector solicitado: %i:%i\n", PS_Buscado.pista, PS_Buscado.sector);
	printf("Sectores recorridos: ");
	tiempoConsumido = sectoresRecorridosCSCAN(posActual, secBuscado, Conf); //Funcion que muestra los sectores recorridos y calcula el tiempo
	printf("\n");
	printf("Tiempo consumido: %f ms\n", tiempoConsumido);
	printf("Próximo sector: %i:%i\n", PS_Proximo.pista, PS_Proximo.sector);

}

float sectoresRecorridosCSCAN (int posActual, int Buscado, config Conf)
{
	int i, j, tiempoSalto, PISTAS, SECTORES, MaxSector, PistaActual, SectorActual, PistaBuscada, SectorBuscado;
	float tiempoGiro, tiempoConsumido;
	ps PS_MaxSector, PS_Actual, PS_Buscado;
	tiempoConsumido = 0;
	tiempoSalto = Conf.t_salto;
	tiempoGiro = tiempoDeGiro (Conf);//tiempo que tarda en recorrer un sector

	PISTAS = Conf.CHS.cilindros;
	SECTORES = Conf.CHS.sectores;
	MaxSector = PISTAS * SECTORES;
	PS_MaxSector = pasarA_pistaSector(MaxSector, Conf);
	PS_Actual = pasarA_pistaSector (posActual, Conf);
	PS_Buscado = pasarA_pistaSector (Buscado, Conf);
	PistaActual = PS_Actual.pista;
	SectorActual = PS_Actual.sector;
	PistaBuscada = PS_Buscado.pista;
	SectorBuscado = PS_Buscado.sector;

	if (posActual == Buscado){
			printf("Ninguno");
	}else if (posActual < Buscado){//el buscado es mayor al actual
		if (PistaActual == PistaBuscada){//Si estan en la misma pista
			for (i=SectorActual+1; i<SectorBuscado; ++i){
				printf("%i:%i, ", PistaActual, i);
				tiempoConsumido = tiempoConsumido + tiempoGiro;
			}
			if (i==SectorBuscado){
				printf("%i:%i", PistaBuscada, SectorBuscado);
			}
		}else {//Esta en otra pista pero antes del tope
			i = SectorActual+1;
			for (j=PistaActual+1; j<PistaBuscada; ++j){
				printf("%i:%i, ", j, i);
				tiempoConsumido = tiempoConsumido + tiempoSalto;
			}
			do{
				printf("%i:%i, ", PistaBuscada, i);
				i = (i+1) % SECTORES;
				tiempoConsumido = tiempoConsumido + tiempoGiro;
			}while(i!=SectorBuscado);
			if (i==SectorBuscado){
				printf("%i:%i", PistaBuscada, SectorBuscado);
			}
		}
	}else{//el buscado es menor al actual---> Hay que subir hasta el tope y despues desde 0:0 al sector indicado
		int MaximaPista = PISTAS - 1;
		int MaximoSector = SECTORES - 1;
		i = SectorActual + 1;
		for (j=PistaActual+1; j<MaximaPista; ++j){
			printf("%i:%i, ", j, i);
			tiempoConsumido = tiempoConsumido + tiempoSalto;
		}
		for (i=SectorActual+1; i<MaximoSector; ++i){
			printf("%i:%i, ", MaximaPista, i);
			tiempoConsumido = tiempoConsumido + tiempoSalto;
		}
		if (i == MaximoSector){
			printf("%i:%i, ", MaximaPista, MaximoSector);//Alcanzamos el tope
		}
		i=0;//Ahora empiezo a subir desde el 0:0
		for (j=0; j<PistaBuscada; ++j){
			printf("%i:%i, ", j, i);
			tiempoConsumido = tiempoConsumido + tiempoSalto;
		}
		for (i=0; i<SectorBuscado; ++i){
			printf("%i:%i, ", PistaBuscada, i);
			tiempoConsumido = tiempoConsumido + tiempoSalto;
		}
		if (i == SectorBuscado){
			printf("%i:%i", PistaBuscada, SectorBuscado);//llegamos al sector solicitado
		}
	}

	return tiempoConsumido;

}
